package vip.liux.gateway.filters.decrypt;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * 加解密、签名工具类
 */
public class CryptoUtil {

    private static final String RSA = "RSA";
    private static final String HMAC_SHA256 = "HmacSHA256";
    private static final String SHA256_WITH_RSA = "SHA256withRSA";

    /**
     * 生成RSA公私钥对（Base64编码）
     *
     * @param keySize 密钥长度（如2048）
     * @return 长度为2的数组，0为Base64公钥，1为Base64私钥
     */
    public static String[] generateRsaKeyPair(int keySize) {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
            keyPairGenerator.initialize(keySize);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            // 公钥(X509)
            String publicKey = Base64.getEncoder().encodeToString(
                    keyPair.getPublic().getEncoded()
            );
            // 私钥(PKCS8)
            String privateKey = Base64.getEncoder().encodeToString(
                    keyPair.getPrivate().getEncoded()
            );
            return new String[]{publicKey, privateKey};
        } catch (Exception e) {
            throw new RuntimeException("生成RSA密钥对失败", e);
        }
    }

    /**
     * RSA解密（Base64编码）
     */
    public static String rsaDecrypt(String encryptedBase64, String base64PrivateKey) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(base64PrivateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        PrivateKey privateKey = KeyFactory.getInstance(RSA).generatePrivate(keySpec);

        javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(RSA);
        cipher.init(javax.crypto.Cipher.DECRYPT_MODE, privateKey);
        byte[] decoded = Base64.getDecoder().decode(encryptedBase64);
        byte[] decryptedBytes = cipher.doFinal(decoded);
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    /**
     * RSA加密（Base64编码）
     */
    public static String rsaEncrypt(String plainText, String base64PublicKey) throws Exception {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey));
        PublicKey publicKey = KeyFactory.getInstance(RSA).generatePublic(keySpec);

        javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(RSA);
        cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, publicKey);
        byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    /**
     * RSA签名（SHA256withRSA）
     */
    public static String rsaSign(String data, String base64PrivateKey) throws Exception {
        byte[] privateKeyBytes = Base64.getDecoder().decode(base64PrivateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        PrivateKey privateKey = KeyFactory.getInstance(RSA).generatePrivate(keySpec);

        Signature signature = Signature.getInstance(SHA256_WITH_RSA);
        signature.initSign(privateKey);
        signature.update(data.getBytes(StandardCharsets.UTF_8));
        byte[] signBytes = signature.sign();
        return Base64.getEncoder().encodeToString(signBytes);
    }

    /**
     * HMAC-SHA256签名
     */
    public static String hmacSha256(String data, String secret) {
        try {
            Mac mac = Mac.getInstance(HMAC_SHA256);
            SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_SHA256);
            mac.init(secretKey);
            byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
            StringBuilder hexResult = new StringBuilder();
            for (byte b : hash) {
                hexResult.append(String.format("%02x", b));
            }
            return hexResult.toString();
        } catch (Exception e) {
            throw new RuntimeException("签名失败", e);
        }
    }

    /**
     * 生成HMAC-SHA256密钥（Base64编码）
     */
    public static String generateHmacSha256Secret() {
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance(HMAC_SHA256);
            keyGen.init(256);
            SecretKeySpec key = (SecretKeySpec) keyGen.generateKey();
            return Base64.getEncoder().encodeToString(key.getEncoded());
        } catch (Exception e) {
            throw new RuntimeException("生成HMAC-SHA256密钥失败", e);
        }
    }

    // 可选main方法测试
    public static void main(String[] args) {
        String[] keyPair = generateRsaKeyPair(2048);
        System.out.println("公钥Base64:\n" + keyPair[0]);
        System.out.println("私钥Base64:\n" + keyPair[1]);
        System.out.println("HMAC-SHA256密钥:\n" + generateHmacSha256Secret());
    }
}